from datetime import datetime, timezone, timedelta
import jwt
from django.contrib.auth import authenticate, get_user_model
from django.contrib.auth.hashers import make_password
from drf_spectacular.utils import extend_schema, extend_schema_view, OpenApiParameter
from rest_framework import viewsets, status
from django.contrib.auth.models import User
from rest_framework.decorators import action
from rest_framework.response import Response
from dj_interview_api_server import settings
from home.auth import JWTAuth
from home.common import check_user, check_verify_code
from home.models import UserProfile, VerifyCode
from home.serializers import UserSerializer, UserProfileSerializer
# 账号注册
@extend_schema_view(
    check=extend_schema(summary='检测账号是否存在',tags=['账号'],description='检测账号信息是否存在',parameters=[
        OpenApiParameter('username', str, OpenApiParameter.QUERY, description='账号'),
        OpenApiParameter('phone', str, OpenApiParameter.QUERY, description='手机号码'),
        OpenApiParameter('email', str, OpenApiParameter.QUERY, description='电子邮箱')
    ]),
    reg=extend_schema(summary="账号注册",tags=['账号'],description='账号注册'),
    login=extend_schema(summary='账号登录',tags=['账号'],description='账号登录'),
)
class UserViewSet(viewsets.GenericViewSet):
    # 指定数据集合
    queryset = User.objects.all()
    # 指定序列化器
    serializer_class = UserSerializer
    # 检测用户名,手机号码,电子邮箱 是否存在
    @action(methods=['get'], detail=False)
    def check(self, request):
        # 获取请求参数
        username = request.query_params.get('username')
        phone = request.query_params.get('phone')
        email = request.query_params.get('email')
        # 过滤条件
        is_valid,detail=None,'参数错误'
        if username:
            is_valid,detail=check_user('username',username)
        elif phone:
            is_valid,detail=check_user('phone',phone)
        elif email:
            is_valid,detail=check_user('email',email)
        # 动态获取用户数据表模型类
        if not is_valid:
            data = {'detail': detail}
            return Response(data, status=status.HTTP_400_BAD_REQUEST)
        return Response(data={'detail': detail}, status=status.HTTP_200_OK)

    @action(methods=['post'],detail=False)
    def reg(self,request):
        # 接收请求参数并序列化
        serializer=UserSerializer(data=request.data)
        # 检测账号是否存在
        username_is_valid, detail = check_user('username', request.data.get('username'))
        if not username_is_valid:
            return Response(data={'detail': detail}, status=status.HTTP_400_BAD_REQUEST)
        email_is_valid, detail = check_user('email', request.data.get('email'))
        if not email_is_valid:
            return Response(data={'detail': detail}, status=status.HTTP_400_BAD_REQUEST)
        phone_is_valid, detail = check_user('phone', request.data.get('phone'))
        if not phone_is_valid:
            return Response(data={'detail': detail}, status=status.HTTP_400_BAD_REQUEST)
        if serializer.is_valid():
            # 将phone字段取出来
            phone=serializer.validated_data.pop('phone')
            # 获取客户端发送的参数
            # 对密码进行加密
            serializer.validated_data['password']=make_password(serializer.validated_data['password'])
            serializer.validated_data['is_active']=True
            # 执行新增操作
            user=serializer.save()
            # 将phone写入用户附加表
            UserProfile.objects.create(user=user,phone=phone)
            return Response(serializer.data,status=status.HTTP_201_CREATED)
        return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST)

    # 账号登录
    @action(methods=['post'], detail=False)
    def login(self, request):
        # 接收请求参数
        username = request.data.get('username')
        phone = request.data.get('phone')
        email = request.data.get('email')
        password = request.data.get('password')
        verify_code=request.data.get('verify_code')
        auth_user=None
        if username:
            # 验证账号和密码
            auth_user = authenticate(username=username, password=password)
        elif phone:
            try:
                # 根据电话号码查询username
                profile=UserProfile.objects.get(phone=phone)
                # 查询验证码信息
                try:
                    is_valid,detail=check_verify_code(phone,verify_code)
                    if not is_valid:
                        return Response(data={'detail': detail}, status=status.HTTP_400_BAD_REQUEST)
                    auth_user = profile.user
                except VerifyCode.DoesNotExist:
                    return Response(data={'detail':'验证码不存在'},status=status.HTTP_400_BAD_REQUEST)
            except UserProfile.DoesNotExist:
                return Response(data={'detail':'手机号码不存在'},status=status.HTTP_400_BAD_REQUEST)
        elif email:
            try: # 根据电子邮箱查询username
                user=User.objects.get(email=email)
                # 验证账号密码
                auth_user = authenticate(username=user.username, password=password)
            except UserProfile.DoesNotExist:
                return Response(data={'detail':'账号不存在'},status=status.HTTP_400_BAD_REQUEST)
        if auth_user:
            # TOKEN中存储的数据
            payload = {
                'user_id': auth_user.id,
                'username': username,
                # 设置token签发时间
                'iat': datetime.now(timezone.utc),
                # 过期时间
                'exp': datetime.now(timezone.utc) + timedelta(hours=1)
            }
            # 生成token
            token = jwt.encode(payload, settings.SECRET_KEY)
            # 更新登录时间
            auth_user.last_login = datetime.now(timezone.utc)
            # 保存更新
            auth_user.save()
            return Response(data={'token': token})
        return Response(data={'detail': '账号或密码错误'}, status=status.HTTP_400_BAD_REQUEST)


@extend_schema_view(
    update_avatar=extend_schema(summary='更新头像',tags=['用户信息'],description='更新用户头像'),
    login_info=extend_schema(summary='获取登录账号信息',tags=['用户信息'],description='获取登录用户信息'),
    update_password=extend_schema(summary='修改密码',tags=['用户信息'],description='修改登录密码')
)
class UserInfoViewSet(viewsets.ViewSet):
    # 登录认证类
    authentication_classes = (JWTAuth,)
    # 获取登录账号信息
    @action(methods=['post'], detail=False)
    def login_info(self, request):
        # 查询用户附加表中的数据
        profile = UserProfile.objects.get(user_id=request.user.id)
        # 调用用户附加表序列化器
        serializer = UserProfileSerializer(profile)
        return Response(data=serializer.data)

    # 更新用户头像
    @action(methods=['patch'],detail=False)
    def update_avatar(self,request):
        # 获取要更新头像的用户数据
        profile=UserProfile.objects.get(user_id=request.user.id)
        # 手动调用序列化器
        serializer = UserProfileSerializer(profile,data=request.data)
        # 判断客户端提交的参数是否合法
        if serializer.is_valid(raise_exception=True):
            # 保存数据: 执行更新操作
            serializer.save()
            return Response(data=serializer.data)

    # 修改登录密码
    @action(methods=['patch'],detail=False)
    def update_password(self,request):
        # 接收请求参数
        old_password=request.data.get('old_password')
        password = request.data.get('password')
        # 动态获用户数据表模型类
        User = get_user_model()
        # 查询当前账号数据 request.user.id
        user = User.objects.get(pk=request.user.id)
        # 验证原始密码是否正确
        is_valid = user.check_password(old_password)
        if not is_valid:
            return Response(data={'detail':'原始密码不正确'},status=status.HTTP_400_BAD_REQUEST)
        # 更新密码
        user.set_password(password)
        # 保存更新
        user.save()
        return Response(data={'detail':'重置密码成功'})










